package com.qianda.qdminiapp.security;

import com.google.common.cache.CacheBuilder;
import org.springframework.security.core.Authentication;
import com.google.common.cache.Cache;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName InMemoryTokenManager
 * @Author cw
 * @Date 2019/7/1 10:29
 **/
public class InMemoryTokenManager implements  TokenManager {

    public static final long DEFAULT_TTL = 1800;

    private long timeToLive;

    private Cache<String, TokenWrapper> tokens;

    /**
     * 创建默认的令牌管理器
     */
    public InMemoryTokenManager() {
        this(DEFAULT_TTL);
    }

    /**
     * 创建默认的令牌管理器
     *
     * @param timeToLive 失活时间单位秒
     */
    public InMemoryTokenManager(long timeToLive) {
        if (timeToLive < 0) {
            timeToLive = 0;
        }
        this.timeToLive = timeToLive;
        this.tokens = CacheBuilder.newBuilder()
                // 最多上千个令牌
                .maximumSize(1000000)
                // 最后访问开始计失效时间
                .expireAfterAccess(timeToLive, TimeUnit.SECONDS).build();
    }

    @Override
    public void invalidateAll() {
        tokens.invalidateAll();
    }

    @Override
    public void invalidate(String tokenId) {
        tokens.invalidate(tokenId);
    }

    @Override
    public Token createToken(Authentication authResult) {
        Token token = new Token();
        TokenWrapper tokenWrapper = new TokenWrapper(token, authResult);

        tokens.put(token.getId(), tokenWrapper);

        return token;
    }

    /**
     * 获取令牌，此方法会导致令牌续期
     */
    @Override
    public Token getToken(String tokenId) {
        TokenWrapper tokenWrapper = tokens.getIfPresent(tokenId);
        if (tokenWrapper != null) {
            return tokenWrapper.getToken();
        }

        return null;
    }

    /**
     * 获取已认证信息，此方法会导致令牌续期
     */
    @Override
    public Authentication getAuthResult(String tokenId) {
        TokenWrapper tokenWrapper = tokens.getIfPresent(tokenId);
        if (tokenWrapper != null) {
            return tokenWrapper.getAuthResult();
        }

        return null;
    }

    public long getTimeToLive() {
        return timeToLive;
    }

    /**
     * 令牌包装，包含令牌值和对应的已认证信息
     *
     * @author gaigeshen
     * @since 11/21 2017
     */
    private final class TokenWrapper {

        private final Token token;
        private final Authentication authResult;

        public TokenWrapper(Token token, Authentication authResult) {
            this.token = token;
            this.authResult = authResult;
        }

        public Token getToken() {
            return token;
        }

        public Authentication getAuthResult() {
            return authResult;
        }
    }


}
